package com.xiaoshuidi.cloud.module.finance.api.finance;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.module.finance.api.finance.dto.BankTransferReqDTO;
import com.xiaoshuidi.cloud.module.finance.api.finance.dto.CarryForwardDTO;
import com.xiaoshuidi.cloud.module.finance.api.finance.dto.CheckPayResultReqDTO;
import com.xiaoshuidi.cloud.module.finance.api.finance.dto.FinanceMoneyFlowDTO;
import com.xiaoshuidi.cloud.module.finance.convert.finance.FinanceConvert;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.finance.FinanceMoneyFlowDO;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.finance.FinanceMoneyFlowMapper;
import com.xiaoshuidi.cloud.module.finance.enums.finance.DirectionEnum;
import com.xiaoshuidi.cloud.module.finance.enums.finance.PaymentSourceEnum;
import com.xiaoshuidi.cloud.module.finance.enums.finance.SourceBizTypeEnum;
import com.xiaoshuidi.cloud.module.finance.enums.order.FinanceCommonStatusEnum;
import com.xiaoshuidi.cloud.module.finance.service.finance.FinanceBankTransferService;
import com.xiaoshuidi.cloud.module.finance.service.finance.FinanceMoneyFlowService;
import org.springframework.util.MultiValueMap;
import org.springframework.util.MultiValueMapAdapter;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
public class FinanceApiImpl implements FinanceApi {
    @Resource
    private FinanceMoneyFlowService financeMoneyFlowService;
    @Resource
    private FinanceMoneyFlowMapper financeMoneyFlowMapper;
    @Resource
    private FinanceBankTransferService financeBankTransferService;

    /**
     * 账单费用实际支付流水
     *
     * @param sourceBizType 来源业务类型 {@link SourceBizTypeEnum}
     * @param reqDTO        需要结转的账单及金额
     * @return
     */
    @Override
    public CommonResult<List<FinanceMoneyFlowDTO>> moneyFlowList(String sourceBizType, List<CarryForwardDTO> reqDTO) {
        LambdaQueryWrapper<FinanceMoneyFlowDO> query = Wrappers.lambdaQuery();
        query.eq(FinanceMoneyFlowDO::getSourceBizType, sourceBizType);
        query.eq(FinanceMoneyFlowDO::getStatus, FinanceCommonStatusEnum.SUCCESS.name());
        query.eq(FinanceMoneyFlowDO::getSourceFrom, PaymentSourceEnum.ONLINE.name());
        query.in(FinanceMoneyFlowDO::getSourceBizId,
                reqDTO.stream().map(CarryForwardDTO::getSourceBizId).collect(Collectors.toList()));
        List<FinanceMoneyFlowDO> financeMoneyFlowDOS = financeMoneyFlowMapper.selectList(query);
        return CommonResult.success(FinanceConvert.INSTANCE.convertApiDOList(financeMoneyFlowDOS));
    }

    /**
     * 换房退租结转, 生成对冲流水
     *
     * @param reqDTO        需要结转的账单及金额
     * @param sourceBizType 来源业务类型 {@link com.xiaoshuidi.cloud.module.finance.enums.finance.SourceBizTypeEnum}
     * @return
     */
    @Override
    public CommonResult<Void> carryForward(String sourceBizType,
                                           List<CarryForwardDTO> reqDTO) {
        // 查询相关流水
        List<FinanceMoneyFlowDO> l = financeMoneyFlowService.getFinanceMoneyFlowListBySourceBizIdAndSourceBizType(
                sourceBizType,
                reqDTO.stream().map(CarryForwardDTO::getSourceBizId).collect(Collectors.toList()));
        // 根据结转对象分组
        Map<CarryForwardDTO, List<FinanceMoneyFlowDO>> m = l.stream().collect(Collectors.groupingBy(flow ->
                reqDTO.stream().filter(r -> r.getSourceBizId().equals(flow.getSourceBizId())
                                && sourceBizType.equals(flow.getSourceBizType())
                                && r.getFromStartTime().isEqual(flow.getRoomRentOrderStart())
                                && r.getFromEndTime().isEqual(flow.getRoomRentOrderEnd()))
                        .findFirst().orElse(new CarryForwardDTO())));

        MultiValueMap<CarryForwardDTO, FinanceMoneyFlowDO> multiValueMap = new MultiValueMapAdapter<>(m);
        List<FinanceMoneyFlowDO> carryForward = new ArrayList<>(reqDTO.size());
        for (CarryForwardDTO carryForwardDTO : multiValueMap.keySet()) {
            if (multiValueMap.getFirst(carryForwardDTO) == null) {
                continue;
            }
            FinanceMoneyFlowDO flow = multiValueMap.getFirst(carryForwardDTO);
            // 原支付流水的对冲流水
            flow.setTradeAmount(carryForwardDTO.getAmount());
            flow.setDirection(DirectionEnum.OUT.getValue());
            flow.setFlowNo(financeMoneyFlowService.nextFlowNo());
            flow.setTradeTime(carryForwardDTO.getActualEndTime().atStartOfDay());
            flow.setPayTime(carryForwardDTO.getActualEndTime().atStartOfDay());
            flow.setRoomRentOrderEnd(carryForwardDTO.getActualEndTime());
            carryForward.add(flow);
            // 结转后的新流水
            FinanceMoneyFlowDO newFlow = FinanceConvert.INSTANCE.convert(carryForwardDTO.getForwardTo());
            // 原流水的支付信息
            newFlow.setDirection(DirectionEnum.IN.getValue());
            newFlow.setRenter(flow.getRenter());
            newFlow.setPayAppId(flow.getPayAppId());
            newFlow.setPayMethod(flow.getPayMethod());
            newFlow.setPayMerchantId(flow.getPayMerchantId());
            newFlow.setPayOrderId(flow.getPayOrderId());
            newFlow.setPayChannelId(flow.getPayChannelId());
            newFlow.setTradeAmount(carryForwardDTO.getAmount());
            newFlow.setFlowNo(financeMoneyFlowService.nextFlowNo());

            carryForward.add(flow);
        }
        if (carryForward.size() > 0) {
            financeMoneyFlowMapper.insertBatch(carryForward);
        }

        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> bankTransfer(BankTransferReqDTO reqDTO) {
        financeBankTransferService.save(reqDTO);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> bankTransferBatch(List<BankTransferReqDTO> reqDTO) {
        financeBankTransferService.saveBatch(reqDTO);
        return CommonResult.success();
    }

    @Override
    public CommonResult<Map<String, BigDecimal>> checkPayResult(CheckPayResultReqDTO reqDTO) {
        List<FinanceMoneyFlowDO> flows = financeMoneyFlowMapper.selectList(new QueryWrapper<FinanceMoneyFlowDO>()
                .eq("source_biz_type", reqDTO.getSourceBizType())
                .in("source_biz_id", reqDTO.getSourceBizId())
        );
        Map<String, List<FinanceMoneyFlowDO>> map = flows.stream().collect(Collectors.groupingBy(FinanceMoneyFlowDO::getSourceBizId));
        Map<String, BigDecimal> result = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, m -> m.getValue().stream().filter(f -> FinanceCommonStatusEnum.SUCCESS.name().equals(f.getStatus()))
                .map(FinanceMoneyFlowDO::getTradeAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
        return CommonResult.success(result);
    }
}
